home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / tkern10.zip / SRC\TPIPE.C < prev    next >
Text File  |  1994-06-25  |  6KB  |  288 lines

  1. /*
  2.  *  This file forms part of "TKERN" - "Troy's Kernel for Windows".
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <fcntl.h>
  22. #include <errno.h>
  23. #include <io.h>
  24. #include <sys/tfile.h>
  25. #include <errno.h>
  26. #include <memory.h>
  27. #include <malloc.h>
  28. #include <string.h>
  29.  
  30. extern    int    nError;
  31. extern    void    tkern_wakeup_call(void);
  32.  
  33. #define    PIPESIZE 2048
  34. #define    READER_CLOSED 1
  35. #define    WRITER_CLOSED 2
  36. #define    CLOSED (READER_CLOSED | WRITER_CLOSED)
  37.  
  38. struct    pipe_struc
  39. {
  40.     int    nReadSeq;
  41.     int    nWriteSeq;
  42.     int    iStart;
  43.     int    iEnd;
  44.     int    flags;
  45.     struct    pipe_struc    *next;
  46.     int    iBuffer;
  47.     char    achBuffer[PIPESIZE + 1];
  48. };
  49.  
  50. static    struct    pipe_struc *pipes = 0;
  51. static    struct    pipe_struc *lastpipe = 0;
  52. static    int    nSeq = 0;
  53.  
  54.  
  55. static void
  56. incseq(void)
  57. {
  58.     nSeq = nSeq + 2;
  59.     if (nSeq > 32000)
  60.         nSeq = 0;
  61. }
  62.  
  63. static void
  64. remove_pipe(int nSeq)
  65. {
  66.     struct pipe_struc **link, *entry;
  67.  
  68.     for (link = &pipes; *link; link = &(*link)->next)
  69.     {
  70.         if ((*link)->nReadSeq == nSeq)
  71.         {
  72.             entry = *link;
  73.             *link = entry->next;
  74.             free(entry);
  75.             return;
  76.         }
  77.     }
  78. }
  79.  
  80. #pragma argsused
  81. int
  82. pipe_open(    char const *pchFile,
  83.         int    nMode,
  84.         int    nAccess)
  85. {
  86.     int    nResult;
  87.     struct    pipe_struc *entry, **link;
  88.  
  89.     if (!strcmp(pchFile, "input"))
  90.     {
  91.         if (lastpipe)
  92.         {
  93.             remove_pipe(lastpipe->nReadSeq);
  94.             lastpipe = 0;
  95.         }
  96.         link = &pipes;
  97.         while (*link)
  98.         {
  99.             if ((*link)->nReadSeq == nSeq)
  100.             {
  101.                 incseq();
  102.                 link = &pipes;
  103.             }
  104.             else
  105.             {
  106.                 link = &(*link)->next;
  107.             }
  108.         }
  109.         entry = (struct pipe_struc *) malloc(sizeof(struct pipe_struc));
  110.         entry->nReadSeq = nSeq;
  111.         entry->nWriteSeq = nSeq + 1;
  112.         entry->next = 0;
  113.         entry->iStart = 1;
  114.         entry->iEnd = 0;
  115.         entry->flags = 0;
  116.         *link = entry;
  117.         lastpipe = entry;
  118.         incseq();
  119.         nError = 0;
  120.         return entry->nReadSeq;
  121.     }
  122.     else if (!strcmp(pchFile, "output"))
  123.     {
  124.         if (!lastpipe)
  125.         {
  126.             nError = EPIPE;
  127.             return -1;
  128.         }
  129.         entry = lastpipe;
  130.         lastpipe = 0;
  131.         nError = 0;
  132.         return entry->nWriteSeq;
  133.     }
  134.     else
  135.     {
  136.         nError = ENODEV;
  137.         return -1;
  138.     }
  139. }
  140.  
  141. int
  142. pipe_close(    int    id)
  143. {
  144.     struct    pipe_struc *entry;
  145.  
  146.     for (entry = pipes; entry; entry = entry->next)
  147.     {
  148.         if (entry->nReadSeq == id)
  149.         {
  150.             entry->flags |= READER_CLOSED;
  151.             if ((entry->flags & CLOSED) == CLOSED)
  152.                 remove_pipe(entry->nReadSeq);
  153.             return 0;
  154.         }
  155.         if (entry->nWriteSeq == id)
  156.         {
  157.             entry->flags |= WRITER_CLOSED;
  158.             if ((entry->flags & CLOSED) == CLOSED)
  159.                 remove_pipe(entry->nReadSeq);
  160.             return 0;
  161.         }
  162.     }
  163.     nError = EFAULT;
  164.     return -1;
  165. }
  166.  
  167. int
  168. pipe_read(    int    id,
  169.         char    *pchData,
  170.         int    nBytes)
  171. {
  172.     int    nAvailable;
  173.     struct    pipe_struc *entry;
  174.     int    nTotal = 0;
  175.  
  176.     if (id & 1)    /* Indicates a write-side */
  177.     {
  178.         nError = EACCES;
  179.         return -1;
  180.     }
  181.     for (entry = pipes; entry; entry = entry->next)
  182.     {
  183.         if (entry->nReadSeq == id)
  184.             break;
  185.     }
  186.     if (!entry)
  187.     {
  188.         nError = EFAULT;
  189.         return -1;
  190.     }
  191.     nAvailable = entry->iEnd - entry->iStart;
  192.     if (nAvailable < 0)
  193.         nAvailable += PIPESIZE + 1;
  194.     if (!nAvailable)
  195.     {
  196.         if (entry->flags & WRITER_CLOSED)
  197.         {
  198.             return 0;
  199.         }
  200.         else
  201.         {
  202.             return FR_NOTREADY;
  203.         }
  204.     }
  205.     if (nAvailable < nBytes)
  206.         nBytes = nAvailable;
  207.     if (nBytes + entry->iStart > PIPESIZE)
  208.     {
  209.         nTotal = PIPESIZE - entry->iStart + 1;
  210.         memcpy(pchData,
  211.                entry->achBuffer + entry->iStart,
  212.                nTotal);
  213.         nBytes -= nTotal;
  214.         pchData += nTotal;
  215.         entry->iStart = 0;
  216.     }
  217.     memcpy(pchData, entry->achBuffer + entry->iStart, nBytes);
  218.     entry->iStart += nBytes;
  219.     nTotal += nBytes;
  220.     tkern_wakeup_call();
  221.     return nTotal;
  222. }
  223.  
  224. int
  225. pipe_write(    int    id,
  226.         char    const    *pchData,
  227.         int    nBytes)
  228. {
  229.     struct    pipe_struc *entry;
  230.     int    nTotal = 0;
  231.     int    nAvailable;
  232.  
  233.     if (!(id & 1))    /* Indicates a read-side */
  234.     {
  235.         nError = EACCES;
  236.         return -1;
  237.     }
  238.     for (entry = pipes; entry; entry = entry->next)
  239.     {
  240.         if (entry->nWriteSeq == id)
  241.             break;
  242.     }
  243.     if (!entry)
  244.     {
  245.         nError = EFAULT;
  246.         return -1;
  247.     }
  248.     if (entry->flags & READER_CLOSED)
  249.     {
  250.         /* Write on a pipe with nobody to read */
  251.         nError = EPIPE;
  252.         return -1;
  253.     }
  254.     nAvailable = entry->iStart - entry->iEnd - 1;
  255.     if (nAvailable < 0)
  256.         nAvailable = nAvailable + PIPESIZE + 1;
  257.     if (nAvailable < nBytes)
  258.         nBytes = nAvailable;
  259.     if (!nAvailable)
  260.     {
  261.         return FR_NOTREADY;
  262.     }
  263.     if (nBytes + entry->iEnd > PIPESIZE)
  264.     {
  265.         nTotal = PIPESIZE - entry->iEnd + 1;
  266.         memcpy(entry->achBuffer + entry->iEnd,
  267.                pchData,
  268.                nTotal);
  269.         nBytes -= nTotal;
  270.         pchData += nTotal;
  271.         entry->iEnd = 0;
  272.     }
  273.     memcpy(entry->achBuffer + entry->iEnd, pchData, nBytes);
  274.     entry->iEnd += nBytes;
  275.     nTotal += nBytes;
  276.     tkern_wakeup_call();
  277.     return nTotal;
  278. }
  279.  
  280. int
  281. pipe_ioctl(void)
  282. {
  283.     nError = EINVAL;
  284.     return -1;
  285. }
  286.  
  287.  
  288.